package com.example.handler;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;
import java.util.Objects;

/**
 * 一个CellWriteHandler，用于合并单元格
 *
 * @author linfeng
 * @date 2022/1/9 11:25
 */
public class LiveRoomStatisticsCellMergeHandler extends AbstractMergeStrategy {

    /**
     * 最大的列的索引（从0开始计数）
     */
    private static final int MAX_COLUMN_INDEX = 6;

    /**
     * 直播间id在第几列（从0开始计数）
     */
    private static final int COLUMN_INDEX_OF_ROOM_ID = 1;

    /**
     * 哪些列需要合并单元格
     */
    private static final int[] COLUMNS_INDEX_NEED_MERGE = {0, 1, 2, 3, 4};

    /**
     * 合并单元格
     * 因为 公司名称、直播间名称、直播观看人次、产品icon点击数 这些字段和直播间id是一对一的关系
     * 所以当两行数据的直播间id相同的时候，把这两行数据的 公司名称、直播间id、直播间名称、直播观看人次、产品icon点击数 合并为一行
     *
     * @param sheet
     * @param cell
     * @param head
     * @param relativeRowIndex
     */
    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
        Integer currentRowIndex = cell.getRowIndex();
        if (isAllColumnsAlreadyWrote(sheet, currentRowIndex)) {
            boolean thisRowsRoomIdEqualsToPreviousRowsRoomId = isThisRowsRoomIdEqualsToPreviousRowsRoomId(sheet, currentRowIndex);
            if (thisRowsRoomIdEqualsToPreviousRowsRoomId) {
                doMergeByRoomId(sheet, cell, head, currentRowIndex);
            }
        }
    }

    /**
     * 判断是否该行的所有列都已经写入
     *
     * @param sheet
     * @param currentRowIndex
     * @return
     */
    private boolean isAllColumnsAlreadyWrote(Sheet sheet, Integer currentRowIndex) {
        Row row = sheet.getRow(currentRowIndex);
        Cell currentCell;
        for (int columnIndex = 0; columnIndex <= MAX_COLUMN_INDEX; ++columnIndex) {
            currentCell = row.getCell(columnIndex);
            if (currentCell == null) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断当前行和上一行的roomId是否相同
     *
     * @param sheet
     * @param currentRowIndex
     * @return 如果当前行的roomId和上一行的roomId相同，则返回true
     */
    private boolean isThisRowsRoomIdEqualsToPreviousRowsRoomId(Sheet sheet, Integer currentRowIndex) {
        Integer previousRowIndex = currentRowIndex - 1;
        if (previousRowIndex <= 0) {
            return false;
        }
        Cell previousRowsRoomIdCell = sheet.getRow(previousRowIndex).getCell(COLUMN_INDEX_OF_ROOM_ID);
        if (previousRowsRoomIdCell == null) {
            return false;
        }
        Cell currentRowsRoomIdCell = sheet.getRow(currentRowIndex).getCell(COLUMN_INDEX_OF_ROOM_ID);
        if (currentRowsRoomIdCell == null) {
            return false;
        }
        String previousRowsRoomId = previousRowsRoomIdCell.getStringCellValue();
        String currentRowsRoomId = currentRowsRoomIdCell.getStringCellValue();
        return Objects.equals(previousRowsRoomId, currentRowsRoomId);
    }


    private void doMergeByRoomId(Sheet sheet, Cell cell, Head head, Integer currentRowIndex) {
        Integer previousRowIndex = currentRowIndex - 1;
        for (int columnIndex : COLUMNS_INDEX_NEED_MERGE) {
            List<CellRangeAddress> cellRangeAddressList = sheet.getMergedRegions();
            boolean isPreviousCellMerged = false;
            CellRangeAddress rangeAddressOfPreviousCell = null;
            int index = -1;
            for (CellRangeAddress cellAddresses : cellRangeAddressList) {
                index++;
                if (cellAddresses.containsRow(previousRowIndex) && cellAddresses.containsColumn(columnIndex)) {
                    isPreviousCellMerged = true;
                    rangeAddressOfPreviousCell = cellAddresses;
                    break;
                }
            }
            if (isPreviousCellMerged) {
                int firstRow = rangeAddressOfPreviousCell.getFirstRow();
                int firstColumn = rangeAddressOfPreviousCell.getFirstColumn();
                rangeAddressOfPreviousCell = new CellRangeAddress(firstRow, currentRowIndex, firstColumn, columnIndex);
                // 如果上一行的单元格已经是合并后的单元格，则需要先取消合并，然后再合并
                sheet.removeMergedRegion(index);
            } else {
                rangeAddressOfPreviousCell = new CellRangeAddress(previousRowIndex, currentRowIndex, columnIndex, columnIndex);
            }
            sheet.addMergedRegion(rangeAddressOfPreviousCell);
        }
    }

}
